/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dca.sistemascontrole.malhadecontrole;

import br.ufrn.dca.controle.QuanserClientException;
import dca.sistemascontrole.domain.VariaveisDeControle;
import dca.sistemascontrole.driver.GerenciadorComunicacao;
import dca.sistemascontrole.exception.LogManager;
import dca.sistemascontrole.exception.QuarserClientNullException;
import dca.sistemascontrole.handler.HandlerMainFrame;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;

/**
 *
 * @author Rafael
 */
public class Controlador extends SwingWorker<VariaveisSistema, VariaveisSistema> {

    long t;
    private Observador observador;
    private MalhaDeControle malhaDeControle;
    private HandlerMainFrame handlerMainFrame;
    private GerenciadorComunicacao gerenciadorComunicacao;

    public Controlador(MalhaDeControle malhaDeControle, HandlerMainFrame handlerMainFrame, GerenciadorComunicacao gerenciadorComunicacao, Observador observador, long t) {
        this.t = t;
        this.observador = observador;
        this.malhaDeControle = malhaDeControle;
        this.handlerMainFrame = handlerMainFrame;
        this.gerenciadorComunicacao = gerenciadorComunicacao;
    }

    @Override
    protected VariaveisSistema doInBackground() throws Exception {
        try {
            double nivelTanqueSuperior = gerenciadorComunicacao.readTanqueSuperior();
            double nivelTanqueInferior = gerenciadorComunicacao.readTanqueInferior();

            VariaveisDeControle variaveisDeControle = malhaDeControle.getValorEscrita(nivelTanqueSuperior, nivelTanqueInferior, t);
            double valorEscrita = gerenciadorComunicacao.escreverValor(variaveisDeControle.getuSaturado());
            variaveisDeControle.setuSaturado(valorEscrita);
            
            if (observador != null) {
                observador.estimar(t, nivelTanqueSuperior, nivelTanqueInferior, valorEscrita);
            }

            return new VariaveisSistema(t, nivelTanqueSuperior, nivelTanqueInferior, variaveisDeControle);
        } catch (QuanserClientException ex) {
            LogManager.logWarning("Aviso - Não existe conexão (Controlador)");
        } catch (QuarserClientNullException ex) {
            LogManager.logWarning("Aviso - Não existe conexão (Controlador)");
        }

        return null;
    }

    @Override
    protected void done() {
        try {
            VariaveisSistema variaveisSistema = get();
            if (variaveisSistema != null) {
                VariaveisDeControle variaveisDeControle = variaveisSistema.variaveisDeControle;
                handlerMainFrame.setVariaveisNivel(variaveisSistema.nivelTanqueSuperior,
                        variaveisSistema.nivelTanqueInferior,
                        variaveisDeControle.getSetPoint(),
                        variaveisDeControle.getErro(),
                        variaveisSistema.t,
                        variaveisDeControle.getReferencia());

                handlerMainFrame.setVariaveisTensao(variaveisDeControle.getuSaturado(),
                        variaveisDeControle.getU(),
                        variaveisDeControle.getUi(),
                        variaveisDeControle.getUp(),
                        variaveisDeControle.getUd(),
                        variaveisSistema.t);
            }
        } catch (InterruptedException ex) {
            LogManager.logErro(ex, "Controlador interrompido.");
        } catch (ExecutionException ex) {
            LogManager.logErro(ex, "Erro na thread do controlador.");
        }
    }

    public void setMalhaDeControle(MalhaDeControle malhaDeControle) {
        this.malhaDeControle = malhaDeControle;
    }

    public void setGerenciadorComunicacao(GerenciadorComunicacao gerenciadorComunicacao) {
        this.gerenciadorComunicacao = gerenciadorComunicacao;
    }
}

class VariaveisSistema {

    public long t;
    public double nivelTanqueSuperior;
    public double nivelTanqueInferior;
    public VariaveisDeControle variaveisDeControle;

    public VariaveisSistema(long t, double nivelTanqueSuperior, double nivelTanqueInferior, VariaveisDeControle variaveisDeControle) {
        this.t = t;
        this.nivelTanqueSuperior = nivelTanqueSuperior;
        this.nivelTanqueInferior = nivelTanqueInferior;
        this.variaveisDeControle = variaveisDeControle;
    }
}
